home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- TITLE IBM-PC Dangerous Disk Utility ver 1.0, 26-Apr-88
-
- ; Based largely on the CHAIN program described below.
- ; DDU is written by Bruce Noblick, 185 Crestview Road, Columbus, Ohio 43202
- ; Phone: (614) 262-4564 evenings and weekends
- ;
- ; CHAIN was written by Steven Georgiades
- ;
- ; IBM-PC/XT File Chain Program
- ; Will respond with a list of the disk clusters that make up the file chain
- ; for the requested file.
- ;
- ; If you are using this program and find it of value, your
- ; contribution in any amount ($5.00 suggested) will be greatly
- ; appreciated. Makes checks payable to Steven M. Georgiades.
- ; Thank you.
- ;
- ; If you have any questions or comments about this or any other
- ; SMG program, call or write:
- ;
- ; Steven M. Georgiades
- ; 701-H South Hayward Street
- ; Anaheim, CA 92804
- ; (714) 826-9549
- ;
-
- IF1
- INCLUDE OPTMAC.LIB
- ENDIF
- GENOPT BFOPAMUV
- CODE SEGMENT
-
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
-
- ORG 5CH
-
- FCB LABEL BYTE
-
- ORG 80H
-
- PARAM LABEL BYTE
-
- ORG 100H
-
- CHAIN: JMP BEGIN
-
- ANDSTR DB ", $"
- ORMSG DB 'Stack Overrun xxxxx',13,10,'$'
- ME1MSG DB 'is already unmarked (free)',13,10,'$'
- ME2MSG DB 'is already marked bad',13,10,'$'
- ME3MSG DB 'is in use by a file',13,10,'$'
- ME4MSG DB 'is reserved',13,10,'$'
- UMMSG DB 'has been unmarked (freed)',13,10,'$'
- MKMSG DB 'has been marked bad',13,10,'$'
- VERMSG DB 'Verify marked xxxxx clusters bad',13,10,'$'
- VEREM1 DB 'Sector xxxxx of system area is bad',13,10,'$'
- BDMSG1 DB 'Bad $'
- FRMSG1 DB 'Free $'
- ALMSG1 DB 'Allocated$'
- FRMSG2 DB ' Clusters on drive x:',13,10,10,'$'
- FRMSG3 DB 13,10,10
- FRMSG4 DB 'Total Clusters = xxxxx',13,10,10
- FRMSG5 DB 'Total Bytes = xxxxxxxx',13,10,'$'
- CHMSG1 DB "The Chain for $"
- CHMSG2 DB " is:",13,10,10,"$"
- CHMSG3 DB 13,10,10
- CHMSG4 DB "Total Clusters in File = XXXXX",13,10,10
- CHMSG5 DB "Physical File Length = XXXXXXXX",13,10
- CHMSG6 DB "Logical File Length = XXXXXXXX ("
- PERCENT DB " 0.00% Waste)",13,10,"$"
- CLSTSTR DB "XXXXX$"
- PCT100 DB "100.0"
- SPECERR DB "Invalid File or Path Specification",7,": $"
- DTTAB LABEL BYTE
- DW 512
- DB 1
- DW 1
- DB 2
- DW 224
- DW 2400
- DB 0F9H
- DW 7
- DW 15
- DW 2
- DW 0
- DW 512
- DB 1
- DW 1
- DB 2
- DW 64
- DW 360
- DB 0FCH
- DW 2
- DW 9
- DW 1
- DW 0
- DW 512
- DB 2
- DW 1
- DB 2
- DW 112
- DW 720
- DB 0FDH
- DW 2
- DW 9
- DW 2
- DW 0
- DW 512
- DB 1
- DW 1
- DB 2
- DW 64
- DW 320
- DB 0FEH
- DW 1
- DW 8
- DW 1
- DW 0
- DW 512
- DB 2
- DW 1
- DB 2
- DW 112
- DW 640
- DB 0FFH
- DW 1
- DW 8
- DW 2
- DW 0
- DTMSG DB 'Using FAT ID byte to construct disk type table',13,10,'$'
- TERRMSG DB 'Media Byte xxxxx not supported',7,13,10,'$'
- PARMSG DB 'Parameters for drive x:',13,10,10
- PARMSG17 DB 'OEM Name: xxxxxxxx',13,10
- PARMSG3 DB 'Bytes/Sector: xxxxx',13,10
- PARMSG2 DB 'Sectors/Cluster: xxxxx',13,10
- PARMSG6 DB 'Reserved Sectors: xxxxx',13,10
- PARMSG5 DB 'Copies/FAT: xxxxx',13,10
- PARMSG7 DB 'Entries/Directory: xxxxx '
- PARMSG8 DB '(Sectors/Directory: xxxxx)',13,10
- PARMSG1 DB 'Sectors/Media: xxxxx '
- PARMSG18 DB '(Bytes/Media: xxxxxxxx)',13,10
- PARMSG16 DB 'Media Byte: xxxxx',13,10
- PARMSG4 DB 'Sectors/FAT: xxxxx',13,10
- PARMSG11 DB 'Sectors/Track: xxxxx',13,10
- PARMSG12 DB 'Sides: xxxxx '
- PARMSG13 DB '(Tracks: xxxxx)',13,10
- PARMSG14 DB 'Hidden sectors: xxxxx',13,10
- PARMSG9 DB '(First Data Sector: xxxxx)',13,10
- PARMSG10 DB '(Highest cluster: xxxxx) '
- PARMSG19 DB '(Bytes/Data: xxxxxxxx)',13,10
- PARMSG15 DB '(Ignored Sectors: xxxxx)'
- CRLF DB 13,10,"$"
- READERR DB 'Error Reading Drive x:',7,13,10,'$'
- CLSTMSG DB 'Cluster xxxxx $'
- ONERMSG DB 'is owned by $'
- BADMSG DB 'is marked as bad',13,10,'$'
- FREEMSG DB 'is not in use by any file',13,10,'$'
- INVALID DB 'does not exist!',7,13,10,'$'
- LOSTMSG DB 'appears to be lost!',7,13,10,'$'
- RESVMSG DB 'is reserved',13,10,'$'
-
- CLSTSEC DW ?
- TOTCLST DW ?
- DIR_LEN DW ?
- DIRBUF DW ?
- DIRSEC DW ?
- DRIVE DB ?
- EOF DW 0FF8H
- BAD DW ?
- OPFLAG DB 0
- FATCOP DB ?
- FATSEC DW ?
- FATSIZE DB 3
- FNAME DB 13 DUP(0)
- PREV DW ?
- RANGE DB 0
- SECSIZE DW ?
- CLUST DW ?
- RDIRLEN DW ?
- NEWSTK DW 0
- NEXTOP DW ?
- SIZLSB DW ?
- SIZMSB DW ?
- STRTSEC DW ?
- FSPEC DB 80 DUP(0)
-
- BEGIN: MOV AH,19H ; Get Default Drive
- INT 21H
- MOV DRIVE,AL ; and Save
- MOV SI,OFFSET PARAM ; Set up Pointer to Parameter
- LODSB ; Read Parameter Length
- CBW
- MOV BX,AX
- MOV BYTE PTR [SI+BX],0 ; Terminate Parameter String
- CALL STRIP
- JNC BEGIN2
- JMP ERROR
- BEGIN2: MOV NEXTOP,SI
- MOV AL,DRIVE ; Read Boot Record
- MOV CX,1
- MOV DX,0
- MOV BX,OFFSET FATBUF
- INT 25H
- JNC BOOT_OK
- JMP RDERROR
- BOOT_OK:
- POPF
- CMP BYTE PTR FATBUF,0E9H
- JZ OKTYPE
- CMP BYTE PTR FATBUF,0EBH
- JZ OKTYPE
- MOV AL,DRIVE
- MOV CX,1
- MOV DX,CX
- MOV BX,OFFSET FATBUF+128
- INT 25H
- JNC CHKTYP
- JMP RDERROR
- CHKTYP: POPF
- MOV AL,BYTE PTR FATBUF+128
- CMP AL,BYTE PTR FATBUF+21
- JZ OKTYPE
- MOV SI,OFFSET DTTAB
- MOV CX,5
- TSTTYP: CMP AL,10[SI]
- JZ MOVTYP
- ADD SI,19
- LOOP TSTTYP
- MOV AL,-9[SI]
- MOV DI,OFFSET TERRMSG+16
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET TERRMSG
- JMP ERROUT
- MOVTYP: MOV DI,OFFSET FATBUF+3
- MOV AX,' '
- MOV CX,4
- REP STOSW
- MOV CX,10
- REP MOVSW
- MOV DX,OFFSET DTMSG
- CALL DOS9
- OKTYPE: MOV AX,FATBUF+11 ; Read Sector Size
- MOV SECSIZE,AX ; and Save
- MOV AL,BYTE PTR FATBUF+13 ; Read Sectors per Cluster
- XOR AH,AH
- MOV CLSTSEC,AX ; and Save
- MOV CX,FATBUF+14 ; Read # of Reserved Sectors
- MOV AL,BYTE PTR FATBUF+16 ; Read # of FAT's
- MOV BX,FATBUF+22 ; Read Sectors per FAT
- MOV FATSEC,BX
- MOV FATCOP,AL
- MUL BX ; Calculate Total FAT Sectors
- ADD CX,AX ; Add to Reserved Sectors
- MOV AX,FATBUF+17 ; Read Number of DIR Entries
- MOV RDIRLEN,AX
- MOV DIR_LEN,AX
- PUSH CX ; Calculate DIR Sectors
- MOV CL,5
- SHL AX,CL
- POP CX
- MOV BX,SECSIZE
- XOR DX,DX
- DIV BX
- ADD DX,-1
- ADC AX,0
- MOV DIRSEC,AX ; Save DIR Sectors
- ADD CX,AX ; Add DIR Sectors to Reserved
- MOV STRTSEC,CX ; Save in STRTSEC
- MOV AX,FATSEC ; Calculate FAT Buffer Size
- MOV BX,SECSIZE
- MUL BX
- MOV BX,AX
- ADD AX,OFFSET FATBUF ; Get DIR Buffer Pointer
- MOV DIRBUF,AX
- MOV AX,FATBUF+19 ; Read Total Sectors on Media
- SUB AX,CX ; Calculate Total Data Clusters
- MOV BX,CLSTSEC
- XOR DX,DX
- DIV BX
- INC AX
- MOV TOTCLST,AX
- CMP AX,4080 ; If Necessary, Adjust FAT Size
- JL FAT_OK
- MOV FATSIZE,4
- MOV EOF,0FFF8H
- FAT_OK: CMP OPFLAG,POPT
- JZ NO_FAT
- JMP FAT_OK1
- NO_FAT: MOV SI,OFFSET FATBUF+3
- MOV DI,OFFSET PARMSG17+17
- MOV CX,4
- REP MOVSW
- LODSW
- MOV DI,OFFSET PARMSG3+25
- CALL DEC5OUT
- CALL STRIP0
- LODSB
- XOR AH,AH
- MOV DI,OFFSET PARMSG2+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG6+25
- CALL DEC5OUT
- CALL STRIP0
- LODSB
- XOR AH,AH
- MOV DI,OFFSET PARMSG5+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG7+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV BX,AX
- MOV DI,OFFSET PARMSG1+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,BX
- MUL SECSIZE
- MOV DI,OFFSET PARMSG18+25
- CALL DEC8OUT
- CALL STRIP0
- LODSB
- XOR AH,AH
- MOV DI,OFFSET PARMSG16+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG4+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG11+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG12+25
- CALL DEC5OUT
- CALL STRIP0
- LODSW
- MOV DI,OFFSET PARMSG14+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,DIRSEC
- MOV DI,OFFSET PARMSG8+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,STRTSEC
- MOV DI,OFFSET PARMSG9+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,TOTCLST
- MOV BX,AX
- MOV DI,OFFSET PARMSG10+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,BX
- DEC AX
- MUL CLSTSEC
- MUL SECSIZE
- MOV DI,OFFSET PARMSG19+25
- CALL DEC8OUT
- CALL STRIP0
- MOV AX,FATBUF+24
- MUL FATBUF+26
- MOV BX,AX
- MOV AX,FATBUF+19
- ADD AX,FATBUF+28
- DIV BX
- OR DX,DX
- JZ NO_ADD2
- INC AX
- JMP SHORT NO_ADD3
- NO_ADD2:
- MOV DX,BX
- NO_ADD3:
- MOV DI,OFFSET PARMSG13+25
- CALL DEC5OUT
- CALL STRIP0
- MOV AX,BX
- SUB AX,DX
- MOV DI,OFFSET PARMSG15+25
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET PARMSG
- JMP CC_OK_3
- FAT_OK1:
- MOV AL,DRIVE ; Read FAT
- MOV CX,FATSEC
- MOV DX,1
- MOV BX,OFFSET FATBUF
- INT 25H
- JNC FAT_OK2
- JMP RDERROR
- FAT_OK2:
- POPF
- MOV AX,EOF
- DEC AX
- MOV BAD,AX
- CMP OPFLAG,BOPT
- JZ GOTB
- CMP OPFLAG,FOPT
- JZ GOTF
- CMP OPFLAG,AOPT
- JZ GOTA
- CMP OPFLAG,MOPT
- JNZ NOTM
- JMP MARKIT
- NOTM:
- CMP OPFLAG,UOPT
- JNZ NOTU
- JMP UNMARK
- NOTU:
- CMP OPFLAG,VOPT
- JNZ NOTV
- JMP VERIFY
- NOTV:
- CMP OPFLAG,OOPT
- JZ RDROOT
- CMP OPFLAG,0
- JZ RDROOT
- JMP ERROR
- GOTB: MOV DX,OFFSET BDMSG1
- JMP SHORT GOTMSG
- GOTF: MOV DX,OFFSET FRMSG1
- JMP SHORT GOTMSG
- GOTA: MOV DX,OFFSET ALMSG1
- GOTMSG: CALL DOS9
- MOV DX,OFFSET FRMSG2
- CALL DOS9
- MOV BX,2
- XOR CX,CX
- CL1: CALL TESTCL
- JNZ CL1
- MOV AX,BX
- DEC AX
- MOV PREV,AX
- CALL OUT_CLST
- INC CX
- CL1D: CALL TESTCL
- JNZ CL1D
- MOV AX,BX
- DEC AX
- DEC AX
- INC CX
- CMP AX,PREV
- PUSHF
- INC AX
- POPF
- JNE CL1G
- MOV RANGE,-1
- JMP SHORT CL1I
- CL1G: CALL SENDEM
- MOV AX,BX
- DEC AX
- CALL OUT_CLST
- CL1I: MOV AX,BX
- DEC AX
- MOV PREV,AX
- JMP CL1D
- CL1J: JMP FINDSK
- RDROOT: CMP OPFLAG,OOPT
- JNZ RDROOT2
- CALL OWNER
- RDROOT2:
- CALL GETROOT
- MOV SI,OFFSET FSPEC+3 ; Point to First Element of Path
- NEXT_FLD:
- MOV DI,OFFSET FNAME ; Point to FileName Buffer
- NEXTCHAR:
- LODSB ; Copy Path Element to FileName
- CMP AL,'\' ; until '\' or nul
- JE GOT_DIR
- STOSB
- OR AL,AL
- JE GOT_FNM
- JMP NEXTCHAR
- GOT_DIR:
- MOV AL,0 ; If '\', Read Subdirectory
- STOSB
- CALL READDIR
- JNC NEXT_FLD ; If No Error, Get Next Dir
- JMP ERROR ; Else Flag Error
- GOT_FNM:
- CALL SRCHFILE ; Read File DIR Info
- JNC NOERR3
- JMP ERROR ; If Error, Say So
- NOERR3: MOV AX,[BX+28] ; Read File Length
- MOV SIZLSB,AX
- MOV DX,[BX+30]
- MOV SIZMSB,DX
- MOV DI,OFFSET CHMSG6+31 ; Convert to ASCII
- CALL DEC8OUT ; Strip Off Leading Zeroes
- CALL STRIP0
- MOV DX,OFFSET CHMSG1 ; Output FileSpec Message
- CALL DOS9
- MOV DX,OFFSET FSPEC
- CALL ALTDOS9
- MOV DX,OFFSET CHMSG2
- CALL DOS9
- MOV BX,[BX+26] ; Read Starting Cluster Number
- XOR CX,CX ; Cluster Count = 0
- OR BX,BX ; If Start Cluster = 0, Done
- JZ LASTCLST
- MOV AX,BX ; Output First Cluster Number
- CALL OUT_CLST
- MOV PREV,BX ; Previous Cluster = First
- INC CX ; Cluster Count = 1
- CALL NEXTCLST ; Get Next Cluster Number
- CMP BX,EOF ; If Last, Skip
- JNB LASTCLST
- CLSTLOOP:
- INC CX ; Increment Cluster Count
- MOV AX,PREV ; If Cluster is Previous + 1,
- INC AX
- CMP AX,BX
- JNE CLSTOUT
- MOV RANGE,-1 ; Set Range Flag
- JMP SHORT NEXTONE
- CLSTOUT:
- CALL SENDEM
- CALL OUT_CLST
- NEXTONE:
- MOV PREV,BX ; Previous = Current
- CALL NEXTCLST ; Get Next Cluster Number
- CMP BX,EOF ; If Not EOF, Repeat
- JB CLSTLOOP
- FINDSK: CMP RANGE,0 ; If Range Flag is Set,
- JE LASTCLST
- MOV AH,2 ; Output " - "
- MOV DL,'-'
- INT 21H
- MOV AX,PREV ; Output Last Cluster of Range
- CALL OUT_CLST
- LASTCLST:
- CMP OPFLAG,0
- JNZ CLSTCNT
- MOV AX,SIZMSB ; If Size = 0, 100% Waste
- OR AX,SIZLSB
- JNZ NOT_ZERO
- MOV SI,OFFSET PCT100
- MOV DI,OFFSET PERCENT
- PUSH CX
- MOV CX,5
- REP MOVSB
- POP CX
- JMP SHORT CLSTCNT
- NOT_ZERO:
- MOV AX,SECSIZE ; Calculate Percent Waste
- MOV BX,CLSTSEC
- MUL BX
- MOV BX,AX
- MUL CX
- SUB AX,SIZLSB
- MOV DX,100
- MUL DX
- DIV BX
- PUSH DX
- XOR DX,DX
- DIV CX
- PUSH DX
- MOV DI,OFFSET PERCENT+2 ; Convert Percent to ASCII
- CALL DEC2OUT
- CALL STRIP0
- POP AX
- MUL BX
- POP DI
- ADD AX,DI
- ADC DX,0
- DIV CX
- MOV DX,100
- MUL DX
- DIV BX
- MOV DI,OFFSET PERCENT+5
- CALL DEC2OUT
- CLSTCNT:
- MOV AX,CX ; Convert Cluster Count to ASCII
- MOV DI,OFFSET CHMSG4+31
- CMP OPFLAG,0
- JZ CC_OK
- MOV DI,OFFSET FRMSG4+22
- CC_OK: CALL DEC5OUT
- CALL STRIP0 ; Strip Off Leading Zeroes
- MOV AX,CLSTSEC ; Calculate Physical File Size
- MUL CX
- MOV CX,SECSIZE
- MUL CX
- MOV DI,OFFSET CHMSG5+31 ; Convert to ASCII
- CMP OPFLAG,0
- JZ CC_OK_2
- MOV DI,OFFSET FRMSG5+22 ; Convert to ASCII
- CC_OK_2:
- CALL DEC8OUT
- CALL STRIP0 ; Strip Off Leading Zeroes
- MOV DX,OFFSET CHMSG3 ; Output Trailer Message
- CMP OPFLAG,0
- JZ CC_OK_3
- MOV DX,OFFSET FRMSG3 ; Output Trailer Message
- CC_OK_3:
- CALL DOS9
- MOV SI,NEXTOP
- CALL STRIP
- JC CC_OK_4
- JMP BEGIN2
- CC_OK_4:
- MOV AX,4C00H ; Exit to DOS
- INT 21H
-
- TESTCL: CMP BX,TOTCLST
- JA TC3
- PUSH BX
- CALL NEXTCLST
- MOV AX,BX
- POP BX
- INC BX
- CMP OPFLAG,BOPT
- JZ TC1
- CMP OPFLAG,FOPT
- JZ TC1A
- OR AX,AX
- JZ TC0
- CMP AX,BAD
- JZ TC0
- CMP AX,AX
- JMP SHORT TC2
- TC0: SUB AX,AX
- INC AX
- JMP SHORT TC2
- TC1A: OR AX,AX
- JMP SHORT TC2
- TC1: CMP AX,BAD
- TC2: RET
- TC3: JMP CL1J
-
- ERROR: MOV DX,OFFSET SPECERR ; Output Error Message
- CALL DOS9
- MOV DX,OFFSET PARAM ; Output FileSpec
- CALL ALTDOS9
- JMP CRLFX
-
- OWNER: CALL GETCLST
- CALL NEXTCLST
- OR BX,BX
- JNZ NOT_FREE
- MOV DX,OFFSET FREEMSG
- JMP CC_OK_3
- NOT_FREE:
- MOV AX,EOF
- CMP BX,AX
- JAE CLSTGOOD
- DEC AX
- CMP BX,AX
- JNE NOT_BAD
- MOV DX,OFFSET BADMSG
- JMP CC_OK_3
- NOT_BAD:
- SUB AX,7
- CMP BX,AX
- JB CLSTGOOD
- MOV DX,OFFSET RESVMSG
- JMP CC_OK_3
- RDERROR:
- POPF
- MOV AL,DRIVE
- ADD AL,'A'
- MOV READERR+20,AL
- MOV DX,OFFSET READERR
- ERROUT: CALL DOS9
- MOV AX,4C01H ; Exit to DOS
- INT 21H
- CLSTGOOD:
- MOV AX,CLUST
- CLSTBACK:
- MOV BX,AX
- CALL PREVCLST
- OR AX,AX
- JNZ CLSTBACK
- MOV CLUST,BX
- CALL GETROOT
- SUB BX,BX
- MOV NEWSTK,BX
- CALL PUSHBX
- LOOK1: CALL SRCHCLST
- JNC FOUND
- MOV SI,DIRBUF
- MOV CX,DIR_LEN
- LOOK2: CALL FINDDIR
- JC LOOK3
- MOV BX,26[SI]
- CALL PUSHBX
- ADD SI,32
- LOOP LOOK2
- LOOK3: CALL POPBX
- JZ BADCLST
- CALL GETADIR
- JMP LOOK1
- BADCLST:
- MOV DX,OFFSET LOSTMSG
- JMP CC_OK_3
- FOUND: SUB BX,BX
- MOV NEWSTK,BX
- CALL PUSHBX
- MOV BX,CLUST
- CALL PUSHBX
- MOV SI,DIRBUF
- CMP BYTE PTR [SI],'.'
- JNZ GOTEM
- MOV BX,26[SI]
- CALL PUSHBX
- BACKTRACK:
- MOV BX,58[SI]
- CALL PUSHBX
- JZ ENDBACK
- PUSH SI
- CALL GETADIR
- POP SI
- JMP BACKTRACK
- ENDBACK:
- CALL POPBX
- CALL GETROOT
- GOTEM: MOV DI,OFFSET FSPEC+2
- UNDO: CALL POPBX
- INT 3
- JZ UNDONE
- MOV CLUST,BX
- CALL SRCHCLST
- MOV SI,OFFSET FNAME
- MOV AL,'\'
- STOSB
- CALL MOVSTR
- CALL POPBX
- CALL PUSHBX
- JZ UNDONE
- PUSH DI
- MOV BX,CLUST
- CALL GETADIR
- POP DI
- DEC DI
- JMP UNDO
- UNDONE: MOV DX,OFFSET ONERMSG
- CALL DOS9
- MOV DX,OFFSET FSPEC
- CALL ALTDOS9
- CRLFX: MOV DX,OFFSET CRLF
- DOS9: MOV AH,9
- INT 21H
- RET
-
- ALTDOS9:
- PUSH SI
- PUSH DX
- MOV SI,DX
- AD1: LODSB
- OR AL,AL
- JZ AD2
- MOV DL,AL
- MOV AH,2
- INT 21H
- JMP AD1
- AD2: POP DX
- POP SI
- RET
-
- MARKIT: CALL GETCLST
- CALL NEXTCLST
- OR BX,BX
- JZ MARKCOM
- MARKERR:
- OR BX,BX
- JZ ME1
- MOV AX,BAD
- CMP BX,AX
- JE ME2
- JA ME3
- SUB AX,7
- CMP BX,AX
- JB ME3
- MOV DX,OFFSET ME4MSG
- JMP CC_OK_3
- ME1: MOV DX,OFFSET ME1MSG
- JMP CC_OK_3
- ME2: MOV DX,OFFSET ME2MSG
- JMP CC_OK_3
- ME3: MOV DX,OFFSET ME3MSG
- JMP CC_OK_3
- UNMARK: CALL GETCLST
- CALL NEXTCLST
- CMP BX,BAD
- JNZ MARKERR
- MARKCOM:
- MOV AX,BX
- MOV BX,CLUST
- XOR AX,BAD
- PUSH AX
- CALL SETCLST
- CALL WRT_FAT
- POP AX
- OR AX,AX
- MOV DX,OFFSET UMMSG
- JZ UMMCOM
- MOV DX,OFFSET MKMSG
- UMMCOM: JMP CC_OK_3
-
- VERIFY: MOV OPFLAG,0
- MOV AL,DRIVE
- MOV CX,STRTSEC
- MOV DX,0
- MOV BX,DIRBUF
- VERLP1: PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- MOV CX,1
- INT 25H
- JC VERER1
- POPF
- POP DX
- POP CX
- POP BX
- POP AX
- INC DX
- LOOP VERLP1
- MOV BX,2
- MOV CX,0
- VERLP2: CMP BX,TOTCLST
- JA VERLP2X
- CLC
- PUSH BX
- MOV DI,DIRBUF
- CALL READCLST
- POP BX
- JC VERMRK
- VERNXT: INC BX
- JMP VERLP2
- VERER1: MOV AX,DX
- MOV DI,OFFSET VEREM1+12
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET VEREM1
- ADD SP,10
- JMP CC_OK_3
- VERLP2X:
- OR CX,CX
- JZ VERLP2Y
- PUSH CX
- CALL WRT_FAT
- POP CX
- VERLP2Y:
- MOV AX,CX
- MOV DI,OFFSET VERMSG+19
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET VERMSG
- JMP CC_OK_3
- VERMRK: MOV CLUST,BX
- MOV AX,BX
- MOV DI,OFFSET CLSTMSG+13
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET CLSTMSG
- CALL DOS9
- CALL NEXTCLST
- OR BX,BX
- JNZ VERERR
- MOV AX,BAD
- MOV BX,CLUST
- CALL SETCLST
- INC CX
- MOV DX,OFFSET MKMSG
- CALL DOS9
- JMP VERNXT
- VERERR: MOV AX,BAD
- CMP BX,AX
- JE VE2
- JA VE3
- SUB AX,7
- CMP BX,AX
- JB VE3
- MOV DX,OFFSET ME4MSG
- VE4: CALL DOS9
- MOV BX,CLUST
- JMP VERNXT
- VE2: MOV DX,OFFSET ME2MSG
- JMP VE4
- VE3: MOV DX,OFFSET ME3MSG
- JMP VE4
-
- WRT_FAT:
- MOV AL,DRIVE
- MOV CX,FATSEC
- MOV DX,1
- MOV AH,FATCOP
- MOV BX,OFFSET FATBUF
- FATLOOP:
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- INT 26H
- POPF
- POP DX
- POP CX
- POP BX
- POP AX
- ADD DX,CX
- DEC AH
- JNZ FATLOOP
- MOV AH,13
- INT 21H
- RET
-
- SETCLST:
- PUSH BX
- CMP FATSIZE,3
- JZ SETC_12
- SHL BX,1
- MOV FATBUF[BX],AX
- JMP SHORT SETC_DONE
- SETC_12:
- PUSH CX
- MOV CX,BX
- SHL CX,1
- ADD BX,CX
- SHR BX,1
- MOV CX,0F000H
- JNC SETC_OK
- MOV CL,4
- SHL AX,CL
- MOV CX,0FH
- SETC_OK:
- AND FATBUF[BX],CX
- OR FATBUF[BX],AX
- POP CX
- SETC_DONE:
- POP BX
- RET
-
- GETCLST:
- MOV SI,OFFSET FSPEC+3
- MOV OPFLAG,0
- OWNER1: MOV DI,SI
- OWNER2: LODSB
- CMP AL,'\'
- JZ OWNER1
- OR AL,AL
- JNZ OWNER2
- MOV SI,DI
- CALL GET_WORD
- MOV CLUST,DX
- MOV BX,DX
- MOV AX,BX
- MOV DI,OFFSET CLSTMSG+13
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET CLSTMSG
- CALL DOS9
- CMP BX,TOTCLST
- JA CLSTBAD
- CMP BX,2
- JB CLSTBAD
- RET
- CLSTBAD:
- MOV DX,OFFSET INVALID
- JMP CC_OK_3
-
- GETROOT:
- MOV AL,DRIVE ; Read Root Directory
- MOV CX,DIRSEC
- MOV DX,STRTSEC
- SUB DX,CX
- MOV BX,DIRBUF
- INT 25H
- POPF
- MOV AX,RDIRLEN
- MOV DIR_LEN,AX
- RET
-
- SENDEM: CMP RANGE,0 ; Else
- JE SE1 ; If Range Flag is Set,
- MOV AH,2 ; Output " - "
- MOV DL,'-'
- INT 21H
- MOV AX,PREV ; Output Last Clstr in Range
- CALL OUT_CLST
- MOV RANGE,0 ; Reset Range Flag
- SE1: MOV DX,OFFSET ANDSTR ; Output ", "
- CALL DOS9
- MOV AX,BX ; Output Cluster Number
- RET
-
- SRCHFILE:
- PUSH AX ; Save Register
- PUSH CX
- PUSH DI
- PUSH SI
- CMP FNAME,'.' ; If Filename Starts with '.',
- JNE SRCHFIL2
- MOV SI,OFFSET FNAME ; Copy Filename to FCB
- MOV DI,OFFSET FCB+1
- MOV CX,11
- SRCHFIL1:
- LODSB
- STOSB
- OR AL,AL
- LOOPNZ SRCHFIL1
- INC CX ; and Pad With Spaces
- DEC DI
- MOV AL,' '
- REP STOSB
- JMP SHORT SRCHFIL3
- SRCHFIL2:
- MOV AX,2900H ; Else Parse Filename
- MOV SI,OFFSET FNAME
- MOV DI,OFFSET FCB
- INT 21H
- SRCHFIL3:
- MOV DI,OFFSET FCB+1 ; Point to Filename in FCB
- MOV SI,DIRBUF ; Point to Start of DIRBUF
- MOV CX,DIR_LEN ; Load DIR Length
- JCXZ SRCHFIL5 ; If Zero, Not Found
- SRCHFIL4:
- PUSH CX ; Save Registers
- PUSH DI
- PUSH SI
- MOV CX,11 ; Compare Filename
- REPE CMPSB
- POP SI ; Restore Registers
- POP DI
- POP CX
- JE SRCHFIL6 ; If Match, Found
- ADD SI,32 ; Else Next DIR Entry
- LOOP SRCHFIL4 ; and Repeat
- SRCHFIL5:
- STC ; Set Error Flag
- JMP SHORT SRCHFIL7 ; Done
- SRCHFIL6:
- MOV BX,SI ; Set Pointer to DIR Entry
- CLC ; Clear Error Flag
- SRCHFIL7:
- POP SI ; Restore Registers
- POP DI
- POP CX
- POP AX
- RET ; Done
-
- READDIR:
- PUSH CX ; Save Registers
- PUSH DI
- PUSH SI
- CALL SRCHFILE ; Search for DIR
- JC READDIR3 ; If Not Found, Error
- MOV BX,[BX+26] ; Get Starting Cluster Number
- OR BX,BX ; If Start Cluster = 0, Error
- STC
- JZ READDIR3
- CALL GETADIR
- READDIR3:
- POP SI ; Restore Registers
- POP DI
- POP CX
- RET ; Done
-
- GETADIR:
- MOV DIR_LEN,0 ; DIR Length = 0
- MOV AX,SECSIZE ; Calculate DIR Entries/Cluster
- MUL CLSTSEC
- MOV CL,5
- SHR AX,CL
- MOV CX,AX
- MOV DI,DIRBUF ; Point to DIR Buffer
- READLOOP:
- CALL READCLST ; Read Cluster
- ADD DIR_LEN,CX ; Increment DIR Length
- CMP BX,EOF ; If Not Last Cluster,
- JB READLOOP ; Get Next Cluster
- RET
-
- PUSHBX: CMP NEWSTK,4096
- JZ PPBXR
- PUSH AX
- MOV AX,BX
- MOV BX,NEWSTK
- INC NEWSTK
- ADD BX,BX
- MOV TABLE[BX],AX
- MOV BX,AX
- POP AX
- PPBX: OR BX,BX
- RET
- PPBXR: MOV AX,NEWSTK
- MOV DI,OFFSET ORMSG+14
- CALL DEC5OUT
- CALL STRIP0
- MOV DX,OFFSET ORMSG
- JMP ERROUT
- POPBX: CMP NEWSTK,0
- JZ PPBXR
- DEC NEWSTK
- MOV BX,NEWSTK
- ADD BX,BX
- MOV BX,TABLE[BX]
- JMP PPBX
-
- FINDDIR:
- JCXZ FINDDIR4
- FINDDIR2:
- CMP BYTE PTR [SI],'.'
- JE FINDDIR3
- CMP BYTE PTR [SI],0E5H
- JE FINDDIR3
- CMP BYTE PTR [SI],0
- JE FINDDIR4
- TEST BYTE PTR [SI+11],10H
- CLC
- JNZ FINDDIR5
- FINDDIR3:
- ADD SI,32
- LOOP FINDDIR2
- FINDDIR4:
- STC
- FINDDIR5:
- RET
-
- SRCHCLST:
- PUSH AX
- PUSH CX
- PUSH DI
- PUSH SI
- MOV SI,DIRBUF
- MOV CX,DIR_LEN
- JCXZ SRCHCLS3
- MOV BX,CLUST
- SRCHCLS1:
- CMP BYTE PTR [SI],'.'
- JE SRCHCLS2
- CMP BYTE PTR [SI],0E5H
- JE SRCHCLS2
- CMP BYTE PTR [SI],0
- JE SRCHCLS3
- CMP BX,[SI+26]
- JE SRCHCLS4
- SRCHCLS2:
- ADD SI,32
- LOOP SRCHCLS1
- SRCHCLS3:
- STC
- JMP SHORT SRCHCLS5
- SRCHCLS4:
- MOV DI,OFFSET FNAME
- CALL UNPARSE
- CLC
- SRCHCLS5:
- POP SI
- POP DI
- POP CX
- POP AX
- RET
-
- PREVCLST:
- PUSH BX
- PUSH CX
- PUSH DX
- MOV DX,BX
- MOV CX,TOTCLST
- DEC CX
- PREVCLS1:
- MOV BX,CX
- INC BX
- CALL NEXTCLST
- CMP BX,DX
- LOOPNE PREVCLS1
- JNE PREVCLS2
- ADD CX,2
- PREVCLS2:
- MOV AX,CX
- POP DX
- POP CX
- POP BX
- RET
-
- UNPARSE:
- PUSH CX
- PUSH DI
- PUSH SI
- MOV CX,8
- CALL UNPARSE1
- MOV AL,'.'
- STOSB
- POP SI
- PUSH SI
- ADD SI,8
- MOV CX,3
- CALL UNPARSE1
- CMP CX,3
- JNE UNPARSE5
- DEC DI
- UNPARSE5:
- MOV AL,0
- STOSB
- POP SI
- POP DI
- POP CX
- RET
- UNPARSE1:
- LODSB
- CMP AL,' '
- JE UNPARSE2
- STOSB
- LOOP UNPARSE1
- UNPARSE2:
- RET
-
-
- MOVSTR: LODSB
- STOSB
- OR AL,AL
- JNZ MOVSTR
- RET
-
- GET_WORD:
- PUSH BX
- XOR DX,DX
- GET_WRD1:
- LODSB
- CMP AL,'0'
- JB GET_WRD2
- CMP AL,'9'
- JA GET_WRD2
- SUB AL,'0'
- CBW
- MOV BX,AX
- MOV AX,10
- MUL DX
- ADD AX,BX
- MOV DX,AX
- JMP GET_WRD1
- GET_WRD2:
- DEC SI
- POP BX
- RET
-
- READCLST:
- PUSH AX ; Save Registers
- PUSH CX
- PUSH DX
- PUSH BX ; Save Registers
- PUSH DI
- MOV AX,BX ; Calculate Absolute Sector #
- SUB AX,2
- MOV CX,CLSTSEC
- MUL CX
- ADD AX,STRTSEC
- MOV DX,AX
- MOV AL,DRIVE
- MOV BX,DI ; Read Cluster
- INT 25H
- JC RCERR
- POPF
- POP DI ; Restore Registers
- POP BX
- CALL NEXTCLST ; Get Next Cluster Number
- MOV AX,CLSTSEC ; Increment Buffer Pointer
- MUL SECSIZE
- ADD DI,AX
- JMP SHORT RCCOM
- RCERR: POPF
- STC
- POP DI
- POP BX
- RCCOM: POP DX ; Restore Registers
- POP CX
- POP AX
- RET ; Done
-
- NEXTCLST:
- CMP FATSIZE,3 ; If FAT Size = 16 Bits,
- JE NEXTCLS1
- SHL BX,1 ; Simply Read Next Cluster #
- MOV BX,FATBUF[BX]
- RET ; Done
- NEXTCLS1:
- PUSH AX ; Save Registers
- PUSH CX
- MOV AX,BX ; Word # = Cluster # * 1.5
- SHL AX,1
- ADD BX,AX
- SHR BX,1
- MOV BX,FATBUF[BX]
- JNC NEXTCLS2 ; If Odd, Use 12 MSB's
- MOV CL,4
- SHR BX,CL
- NEXTCLS2:
- AND BX,0FFFH ; Else Use 12 LSB's
- POP CX ; Restore Registers
- POP AX
- RET ; Done
-
- STRIP: LODSB ; Strip Off Leading Whitespace
- CMP AL,' '
- JE STRIP
- CMP AL,9
- JE STRIP
- OR AL,AL ; If End-of-Parameter, Error
- JNZ NOERR1
- STC
- RET
- NOERR1: DEC SI ; ReUse Last Character
- MOV OPFLAG,0
- MOV DI,OFFSET FSPEC ; Point to FileSpec Buffer
- CALL UPPER3
- CMP BYTE PTR [SI+1],':' ; If 2nd Character is Colon,
- JNE GETPATH
- SUB AL,'A' ; Get Drive Number
- MOV DRIVE,AL
- ADD SI,2 ; and Scan Past
- GETPATH:
- MOV AL,DRIVE ; Get Drive Number
- ADD AL,'A' ; Convert to Drive letter
- MOV AH,':' ; and Add Colon
- STOSW ; and place in FileSpec
- MOV PARMSG+21,AL
- MOV FRMSG2+19,AL
- CMP BYTE PTR [SI],'\' ; If Next Character is not '\',
- JE COPYPATH
- MOV AL,'\'
- STOSB
- PUSH SI ; Get Current Path to FileSpec
- MOV SI,DI
- MOV AH,47H
- MOV DL,DRIVE
- INC DL
- INT 21H
- POP SI
- MOV AL,0 ; Find End-of-FileSpec
- MOV CX,64
- REPNE SCASB
- JE NOERR2
- JMP ERROR
- NOERR2: DEC DI
- CMP BYTE PTR [DI-1],'\' ; If Root DIR, Skip
- JE COPYPATH
- MOV AL,'\' ; End-of-FileSpec = '\'
- STOSB
- COPYPATH:
- LODSB ; Copy Rest of Parameter
- CMP AL,'/' ; Until options
- JZ GOTOPT
- CMP AL,' ' ; Or end of filespec
- JZ COPYDONE
- OR AL,AL
- JZ COPYDONE
- STOSB
- JMP COPYPATH
- GOTOPT: LODSB
- CALL UPPER3
- TESTOP BFOPAMUV,SETOPT
- JMP ERROR
- SETOPT: MOV OPFLAG,AH
- INC SI
- COPYDONE:
- DEC SI
- MOV AL,0 ; Set End-of-FileSpec
- STOSB
- MOV DX,OFFSET FSPEC ; Convert to Upper Case
-
- UPPER: PUSH AX ; Save Registers
- PUSH DI
- PUSH SI
- MOV SI,DX ; Set Up Source Index
- MOV DI,DX ; Set Up Destination Index
- UPPER1: LODSB ; Read From Source
- OR AL,AL ; If EOS, Done
- JZ UPPER2
- CALL UPPER3
- STOSB ; Save in Destination
- JMP UPPER1 ; Repeat
- UPPER2: POP SI ; Restore Registers
- POP DI
- POP AX
- RET ; Done
- UPPER3: CMP AL,'a' ; If Lower Case,
- JL UPPER4
- CMP AL,'z'
- JG UPPER4
- SUB AL,'a'-'A' ; Convert to Upper Case
- UPPER4: RET
-
- OUT_CLST:
- PUSH AX ; Save Registers
- PUSH DX
- PUSH DI
- MOV DI,OFFSET CLSTSTR+5 ; Convert Cluster # to Decimal
- CALL DEC5OUT
- CALL STRIP0 ; Strip Off Leading Zeroes
- MOV DI,OFFSET CLSTSTR ; Output Cluster Number
- MOV AH,5
- OUT_CLS0:
- CMP BYTE PTR [DI],' '
- JNZ OUT_CLS1
- INC DI
- DEC AH
- JMP OUT_CLS0
- OUT_CLS1:
- MOV DX,DI
- CALL DOS9
- POP DI ; Restore Registers
- POP DX
- POP AX
- RET ; Done
-
- STRIP0: CMP BYTE PTR [DI],'0' ; If Character != '0', Done
- JNE STRIP1
- CMP BYTE PTR [DI+1],'0' ; If Next Character != Digit,
- JL STRIP1 ; Done
- CMP BYTE PTR [DI+1],'9'
- JG STRIP1
- MOV BYTE PTR [DI],' ' ; Change '0' to ' '
- INC DI ; Point to Next Character
- JMP STRIP0 ; Repeat
- STRIP1: RET ; Done
-
- DEC2OUT:
- PUSH AX ; Save Registers
- PUSH BX
- D2O1: XOR AH,AH ; Clear AH
- MOV BL,10 ; AH=AX%10,AL=AX/10
- DIV BL
- ADD AX,'00' ; Convert to ASCII
- SUB DI,2
- MOV [DI],AX ; Store in String
- POP BX ; Restore Registers
- POP AX
- RET ; Done
-
- DEC4OUT:
- PUSH AX ; Save Registers
- PUSH BX
- D4O1: MOV BL,100 ; AH=AX%100,AL=AX/100
- DIV BL
- XCHG AH,AL ; Convert 2 LSD's
- CALL DEC2OUT
- XCHG AH,AL ; Convert 2 MSD's
- JMP D2O1 ; Using common code
-
- DEC5OUT:
- PUSH AX ; Save Registers
- PUSH BX
- PUSH DX ; DX=AX%10000,AX=AX/10000
- MOV BX,10000
- XOR DX,DX
- DIV BX
- XCHG DX,AX ; Convert 4 LSD's
- CALL DEC4OUT
- ADD DL,'0' ; Convert MSD
- DEC DI
- MOV [DI],DL
- POP DX ; Restore Registers
- POP BX
- POP AX
- RET ; Done
-
- DEC8OUT:
- PUSH AX ; Save Registers
- PUSH BX
- PUSH DX
- MOV BX,10000 ; DX=DX:AX%10000,AX=DX:AX/10000
- DIV BX
- XCHG DX,AX ; Convert 4 LSD's
- CALL DEC4OUT
- XCHG DX,AX ; Convert 4 MSD's
- POP DX
- JMP D4O1 ; Using common code
-
- TABLE LABEL WORD
- FATBUF EQU TABLE+8192
-
- CODE ENDS
-
- END CHAIN
- vert 4 MSD's
- POP DX
- JMP D4O1 ; Using common code
-
- TABLE LABEL WORD
- FATBUF EQU TABLE+8192
-
- COD